package com.icongyou.enterprise.talent_analysis.service;

import com.icongyou.enterprise.talent_analysis.entity.AIInsightCache;
import com.icongyou.enterprise.talent_analysis.mapper.AIInsightCacheMapper;
import com.icongyou.enterprise.talent_analysis.service.impl.AIInsightCacheServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.icongyou.enterprise.talent_analysis.service.AIInsightService;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDateTime;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

/**
 * AI洞察缓存服务测试
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("AI洞察缓存服务测试")
class AIInsightCacheServiceImplTest {

    @Mock
    private AIInsightService aiInsightService;
    
    @Mock
    private AIInsightCacheMapper cacheMapper;
    
    @Mock
    private ObjectMapper objectMapper;

    @InjectMocks
    private AIInsightCacheServiceImpl service;

    @BeforeEach
    void setUp() {
        // Mock对象自动注入
    }

    @Test
    @DisplayName("获取缓存 - 缓存命中且未过期")
    void testGetCache_Hit_NotExpired() throws Exception {
        // Arrange
        String studentId = "student-1";
        String templateId = "template-1";
        
        AIInsightCache cache = createValidCache(studentId, templateId);
        cache.setExpireAt(LocalDateTime.now().plusDays(1));
        
        when(cacheMapper.selectByStudentAndTemplate(studentId, templateId))
            .thenReturn(cache);
        when(objectMapper.readValue(anyString(), eq(com.icongyou.enterprise.talent_analysis.entity.StudentInsight.class)))
            .thenReturn(new com.icongyou.enterprise.talent_analysis.entity.StudentInsight());

        // Act
        var result = service.getFromCache(studentId, templateId);

        // Assert
        assertNotNull(result);
        verify(cacheMapper).selectByStudentAndTemplate(studentId, templateId);
    }

    @Test
    @DisplayName("获取缓存 - 缓存不存在")
    void testGetCache_Miss() {
        // Arrange
        when(cacheMapper.selectByStudentAndTemplate(anyString(), anyString()))
            .thenReturn(null);

        // Act
        var result = service.getFromCache("student-1", "template-1");

        // Assert
        assertNull(result);
    }

    @Test
    @DisplayName("保存缓存 - 新建缓存")
    void testSaveCache_New() throws Exception {
        // Arrange
        String studentId = "student-1";
        String templateId = "template-1";
        var insight = new com.icongyou.enterprise.talent_analysis.entity.StudentInsight();
        insight.setAiModelVersion("GPT-4");
        
        when(cacheMapper.selectByStudentAndTemplate(studentId, templateId))
            .thenReturn(null);
        when(objectMapper.writeValueAsString(any())).thenReturn("{\"test\":\"data\"}");
        when(cacheMapper.insert(any(AIInsightCache.class))).thenReturn(1);

        // Act
        service.putToCache(studentId, templateId, insight);

        // Assert
        ArgumentCaptor<AIInsightCache> captor = ArgumentCaptor.forClass(AIInsightCache.class);
        verify(cacheMapper).insert(captor.capture());
        
        AIInsightCache saved = captor.getValue();
        assertEquals(studentId, saved.getStudentId());
        assertEquals(templateId, saved.getTemplateId());
        assertEquals(0, saved.getVersion());
        assertNotNull(saved.getExpireAt());
    }

    @Test
    @DisplayName("保存缓存 - 更新现有缓存")
    void testSaveCache_Update() throws Exception {
        // Arrange
        String studentId = "student-1";
        String templateId = "template-1";
        var insight = new com.icongyou.enterprise.talent_analysis.entity.StudentInsight();
        
        AIInsightCache existing = createValidCache(studentId, templateId);
        existing.setVersion(1);
        
        when(cacheMapper.selectByStudentAndTemplate(studentId, templateId))
            .thenReturn(existing);
        when(objectMapper.writeValueAsString(any())).thenReturn("{\"updated\":\"data\"}");
        when(cacheMapper.updateByIdWithVersion(any(AIInsightCache.class)))
            .thenReturn(1);

        // Act
        service.putToCache(studentId, templateId, insight);

        // Assert
        verify(cacheMapper).updateByIdWithVersion(any(AIInsightCache.class));
    }

    @Test
    @DisplayName("保存缓存 - 设置过期时间")
    void testSaveCache_ExpirationTime() throws Exception {
        // Arrange
        var insight = new com.icongyou.enterprise.talent_analysis.entity.StudentInsight();
        
        when(cacheMapper.selectByStudentAndTemplate(anyString(), anyString()))
            .thenReturn(null);
        when(objectMapper.writeValueAsString(any())).thenReturn("{}");
        when(cacheMapper.insert(any(AIInsightCache.class))).thenReturn(1);

        LocalDateTime before = LocalDateTime.now().plusHours(24);

        // Act
        service.putToCache("student-1", "template-1", insight);

        // Assert
        ArgumentCaptor<AIInsightCache> captor = ArgumentCaptor.forClass(AIInsightCache.class);
        verify(cacheMapper).insert(captor.capture());
        
        LocalDateTime expireAt = captor.getValue().getExpireAt();
        LocalDateTime after = LocalDateTime.now().plusHours(24);
        
        assertTrue(expireAt.isAfter(before.minusSeconds(1)) && 
                   expireAt.isBefore(after.plusSeconds(1)),
            "过期时间应设置为24小时后");
    }

    @Test
    @DisplayName("清除学生缓存")
    void testInvalidateStudentCache() {
        // Arrange
        String studentId = "student-1";
        when(cacheMapper.deleteByStudentId(studentId)).thenReturn(2);

        // Act
        service.invalidateStudentCache(studentId);

        // Assert
        verify(cacheMapper).deleteByStudentId(studentId);
    }

    @Test
    @DisplayName("清除模板缓存")
    void testInvalidateTemplateCache() {
        // Arrange
        String templateId = "template-1";
        when(cacheMapper.deleteByTemplateId(templateId)).thenReturn(5);

        // Act
        service.invalidateTemplateCache(templateId);

        // Assert
        verify(cacheMapper).deleteByTemplateId(templateId);
    }



    @Test
    @DisplayName("判断缓存是否过期 - 有效缓存")
    void testIsCacheExpired_NotExpired() {
        // Arrange
        AIInsightCache cache = createValidCache("student-1", "template-1");
        when(cacheMapper.selectByStudentAndTemplate(anyString(), anyString()))
            .thenReturn(cache);

        // Act
        boolean expired = service.isCacheExpired("student-1", "template-1");

        // Assert
        assertFalse(expired);
    }

    @Test
    @DisplayName("判断缓存是否过期 - 已过期或不存在")
    void testIsCacheExpired_Expired() {
        // Arrange
        when(cacheMapper.selectByStudentAndTemplate(anyString(), anyString()))
            .thenReturn(null);

        // Act
        boolean expired = service.isCacheExpired("student-1", "template-1");

        // Assert
        assertTrue(expired);
    }

    // ==================== Helper Methods ====================

    private AIInsightCache createValidCache(String studentId, String templateId) {
        AIInsightCache cache = new AIInsightCache();
        cache.setId("cache-id");
        cache.setStudentId(studentId);
        cache.setTemplateId(templateId);
        cache.setInsightJson("{\"insights\":[]}");
        cache.setAiModelVersion("GPT-4");
        cache.setGeneratedAt(LocalDateTime.now());
        cache.setUpdatedAt(LocalDateTime.now());
        cache.setExpireAt(LocalDateTime.now().plusDays(7));
        cache.setVersion(1);
        return cache;
    }
}
